package czk.jvm.lecture.gc;

/**
 * 另外值得注意的是，代码中有两段完全相同的片段，执行结果却是一次逃脱一次失败了。
 * 这是因为任何一个对象的 finalize () 都只会被系统自动调用一次，如果对象面临下一次回收，它的 finalize () 方法不会被再次执行，因此第二段代码的自救行动失败了。
 * @Author:ChenZhangKun
 * @Date: 2022/9/3 21:59
 */
public class FinalizeEscapeGc {
    public static FinalizeEscapeGc SAVA_HOOK = null;

    public void isAlive() {
        System.out.println("yes, i am still alive");
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize method executed");
        FinalizeEscapeGc.SAVA_HOOK = this;
    }

    public static void main(String[] args) throws InterruptedException {
        SAVA_HOOK = new FinalizeEscapeGc();

        // 对象第一次成功拯救自己
        SAVA_HOOK = null;
        System.gc();

        // 因为Finalizer方法的优先级很低，暂停0.5秒，以等待它
        Thread.sleep(500);
        if (SAVA_HOOK != null) {
            // SAVA_HOOK对象的finalize() 确实被垃圾收集器触发过，并且在被收集前成功逃脱了
            SAVA_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead");
        }

        // 下边的代码与上边的完全相同，但是这次自救失败了
        SAVA_HOOK = null;
        System.gc();

        // 因为Finalizer方法的优先级很低，暂停0.5秒，以等待它
        Thread.sleep(500);
        if (SAVA_HOOK != null) {
            SAVA_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead");
        }
    }
}
